package com.tcoding.client.gui.main;

import com.jfoenix.controls.*;
import com.tcoding.client.MainDemo;
import com.tcoding.client.bean.MenuVoCell;
import com.tcoding.client.components.CFImage;
import com.tcoding.client.components.extend.SnackbarExtend;
import com.tcoding.client.datafx.ExtendedAnimatedFlowContainer;
import com.tcoding.client.privilege.user.ProfileController;
import com.tcoding.client.utils.ImageUtil;
import com.tcoding.client.websocket.*;
import com.tcoding.core.vo.MenuVO;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.Flow;
import io.datafx.controller.flow.FlowException;
import io.datafx.controller.flow.FlowHandler;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FXMLViewFlowContext;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.controller.flow.context.ViewFlowContext;
import javafx.animation.Transition;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.ListProperty;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventTarget;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import lombok.extern.slf4j.Slf4j;
import com.tcoding.client.gui.BaseController;
import com.tcoding.client.gui.sidemenu.SideMenuController;
import com.tcoding.client.store.ApplicationStore;
import org.apache.commons.lang3.StringUtils;
import org.kordamp.ikonli.javafx.FontIcon;

import javax.annotation.PostConstruct;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static io.datafx.controller.flow.container.ContainerAnimations.SWIPE_LEFT;
import static io.datafx.controller.flow.container.ContainerAnimations.SWIPE_RIGHT;

@Slf4j
@ViewController(value = "/fxml/Main.fxml", title = "Material Design Example")
public final class MainController extends BaseController {

    @FXMLViewFlowContext
    private ViewFlowContext context;
    @ActionHandler
    private FlowActionHandler actionHandler;
    @FXML
    private StackPane root;

    private SnackbarExtend snackbar;
    @FXML
    private StackPane titleBurgerContainer;
    @FXML
    private JFXHamburger titleBurger;

    @FXML
    private JFXDrawersStack drawersStack;

    @FXML
    private JFXDrawer leftDrawer;
    @FXML
    private JFXDrawer rightDrawer;
    @FXML
    private JFXTabPane tabPane;

    private JFXPopup toolbarPopup;

    @FXML
    private JFXBadge badgeBell;

    @FXML
    private MenuBar mainMenus;

    @FXML
    private MenuBar rightMenuBar;

    @FXML
    private StackPane userAvatar;

    private ResourceBundle bundle;

    /**
     * init fxml when loaded.
     */
    @PostConstruct
    public void init() throws Exception {
        bundle = getBundle();
        // init the title hamburger icon
        final JFXTooltip burgerTooltip = new JFXTooltip("展开菜单");
        leftDrawer.setDefaultDrawerSize(180);
        leftDrawer.setResizeContent(true);
        leftDrawer.setOverLayVisible(false);
        leftDrawer.setResizableOnDrag(true);

        rightDrawer.setDefaultDrawerSize(180);
        rightDrawer.setResizeContent(false);
        rightDrawer.setOverLayVisible(true);

        leftDrawer.setOnDrawerOpening(e -> {
            final Transition animation = titleBurger.getAnimation();
            burgerTooltip.setText("关闭菜单");
            animation.setRate(1);
            animation.play();
        });
        leftDrawer.setOnDrawerClosing(e -> {
            final Transition animation = titleBurger.getAnimation();
            burgerTooltip.setText("展开菜单");
            animation.setRate(-1);
            animation.play();
        });
        drawersStack.toggle(leftDrawer);
        titleBurgerContainer.setOnMouseClicked(e -> {
            drawersStack.toggle(leftDrawer);
        });
        userAvatar.setOnMouseClicked(e-> drawersStack.toggle(rightDrawer));

        badgeBell.textProperty().bind(ApplicationStore.bellNumberProperty());

        tabPane.setId("systemTabPane");
        tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS);

        JFXTooltip.setVisibleDuration(Duration.millis(3000));
        JFXTooltip.install(titleBurgerContainer, burgerTooltip, Pos.BOTTOM_CENTER);

        // create the inner flow and content
//        context = new ViewFlowContext();
        context.register("ContentPane", tabPane);
        context.register("RightDrawer", rightDrawer);
        //初始化左侧菜单
        initSideMenu();
        //初始化右侧个人信息栏
        initProfile();
        //初始化头部菜单
        initMenuBar();
        initTopMenu();
        snackbar = new SnackbarExtend(root,"INFO");
        snackbar.setPrefWidth(300);
        //初始化事件监听
        initListener();
    }

    private void initTopMenu(){
        String language = Locale.getDefault().getLanguage();
        ListProperty<MenuVoCell> listProperty = ApplicationStore.getMenuVoCells();
        listProperty.sort(Comparator.comparing(o -> o.getMenuVO().getOrderNum()));

        List<MenuItem> allItem = new ArrayList<>();
        mainMenus.getMenus().clear();

        Menu allMenu = new Menu(StringUtils.equals(language,"zh")?"菜单":"menu");
        for (MenuVoCell menuVoCell : listProperty) {
            MenuVO menuVO = menuVoCell.getMenuVO();
            ObservableList<MenuVO> childrenMenus = menuVoCell.getChildrenMenus();
            if(childrenMenus==null||childrenMenus.isEmpty()){
                MenuItem menuItem = new MenuItem(StringUtils.equals(language,"zh")?menuVO.getTitle():menuVO.getCode());
                menuItem.setUserData(menuVO);
                allMenu.getItems().add(menuItem);
                allItem.add(menuItem);
                continue;
            }

            Menu menu = new Menu(StringUtils.equals(language,"zh")?menuVO.getTitle():menuVO.getCode());
            for (MenuVO childrenMenu : childrenMenus) {
                MenuItem menuItem = new MenuItem(StringUtils.equals(language,"zh")?childrenMenu.getTitle():childrenMenu.getCode());
                menuItem.setUserData(childrenMenu);
                menu.getItems().add(menuItem);
                allItem.add(menuItem);
            }
            allMenu.getItems().add(menu);
        }

        mainMenus.getMenus().add(allMenu);

        for (MenuItem menuItem : allItem) {

            menuItem.setOnAction(e->{
                MenuItem target = (MenuItem)e.getTarget();
                MenuVO menuVO = (MenuVO)target.getUserData();
                try {
                    SideMenuController.addTab(menuVO.getTitle(),null,menuVO.getHref(),menuVO,tabPane);
                } catch (ClassNotFoundException classNotFoundException) {
                    classNotFoundException.printStackTrace();
                }
            });
        }


    }

    /**
     * 初始化左侧菜单
     *
     * @throws FlowException
     */
    private void initSideMenu() throws FlowException {
        final Duration containerAnimationDuration = Duration.millis(320);
        Flow sideMenuFlow = new Flow(SideMenuController.class);
        final FlowHandler sideMenuFlowHandler = sideMenuFlow.createHandler(context);
        leftDrawer.setSidePane(sideMenuFlowHandler.start(new ExtendedAnimatedFlowContainer(containerAnimationDuration,
                SWIPE_LEFT)));
    }

    private void initProfile() throws FlowException {
        final Duration containerAnimationDuration = Duration.millis(320);
        Flow profileFlow = new Flow(ProfileController.class);
        final FlowHandler profileFlowHandler = profileFlow.createHandler(context);
        rightDrawer.setSidePane(profileFlowHandler.start(new ExtendedAnimatedFlowContainer(containerAnimationDuration,
                SWIPE_RIGHT)));
    }

    /**
     * 初始化上方菜单
     */
    private void initMenuBar() {
        rightMenuBar.getMenus().clear();

        Menu menuProfile = new Menu("");
        FontIcon fontIconProfile = new FontIcon("fas-ellipsis-h");
        menuProfile.setGraphic(fontIconProfile);

        MenuItem profileAction = new MenuItem(bundle.getString("profile"));
        FontIcon profileIcon = new FontIcon("far-user");
        profileAction.setGraphic(profileIcon);

        FontIcon logoutIcon = new FontIcon("fas-power-off");
        MenuItem logoutAction = new MenuItem(bundle.getString("logout"));
        logoutAction.setGraphic(logoutIcon);

        MenuItem switchLanguageAction = new MenuItem(bundle.getString("switchLanguage"));
        FontIcon switchLanguageIcon = new FontIcon("fas-language");
        switchLanguageAction.setGraphic(switchLanguageIcon);

        Menu themeAction = new Menu(bundle.getString("switchTheme"));
        FontIcon themeIcon = new FontIcon("far-image");
        themeAction.setGraphic(themeIcon);

        MenuItem darkTheme = new MenuItem(bundle.getString("darkTheme"));
        MenuItem lightTheme = new MenuItem(bundle.getString("lightTheme"));
        themeAction.getItems().addAll(darkTheme, lightTheme);


        menuProfile.getItems().add(profileAction);
        menuProfile.getItems().add(switchLanguageAction);
        menuProfile.getItems().add(themeAction);
        menuProfile.getItems().add(logoutAction);

        darkTheme.setOnAction((ActionEvent t) -> {
            Scene scene = root.getScene();
            ObservableList<String> stylesheets = scene.getStylesheets();
            String old = "";
            for (String stylesheet : stylesheets) {
                System.out.println(stylesheet);
                if (StringUtils.indexOf(stylesheet, "jfoenix-main") >= 0) {
                    old = stylesheet;
                    break;
                }
            }
            stylesheets.add(MainDemo.class.getResource("/css/theme/jfoenix-main-dark.css").toExternalForm());
            stylesheets.remove(old);
            ApplicationStore.setTheme("dark");
            try {
                initSideMenu();
            } catch (FlowException e) {
                e.printStackTrace();
            }
            initTopMenu();
        });

        lightTheme.setOnAction((ActionEvent t) -> {
            Scene scene = root.getScene();
            ObservableList<String> stylesheets = scene.getStylesheets();
            String old = "";
            for (String stylesheet : stylesheets) {
                System.out.println(stylesheet);
                if (StringUtils.indexOf(stylesheet, "jfoenix-main") >= 0) {
                    old = stylesheet;
                    break;
                }
            }
            stylesheets.add(MainDemo.class.getResource("/css/theme/jfoenix-main-light.css").toExternalForm());
            stylesheets.remove(old);

            ApplicationStore.setTheme("light");
            try {
                initSideMenu();
            } catch (FlowException e) {
                e.printStackTrace();
            }
            initTopMenu();
        });

        switchLanguageAction.setOnAction((ActionEvent t) -> {
            String language = Locale.getDefault().getLanguage();
            if (StringUtils.equals(language, "zh")) {
                Locale.setDefault(new Locale("en", "US"));
            } else {
                Locale.setDefault(new Locale("zh", "CN"));
            }

            reloadBundle();
            bundle = getBundle();
            try {
                initSideMenu();
                initTopMenu();
            } catch (FlowException e) {
                e.printStackTrace();
            }
            initMenuBar();
        });

        logoutAction.setOnAction((ActionEvent t) -> {

            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("确认");
            alert.setHeaderText("确定退出吗？");
            Button btnOk = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
            Button btnCancel = (Button) alert.getDialogPane().lookupButton(ButtonType.CANCEL);
            btnOk.setOnAction(event -> {
                try {
//                    actionHandler.navigate(LoginController.class);
                    Stage mainStage =(Stage) root.getScene().getWindow();
                    mainStage.close();
                    MainDemo.openLoginWindow(context,new Stage());

                } catch (Exception e) {
                    e.printStackTrace();
                }
                ApplicationStore.setName("");
                ApplicationStore.getAllMenu().clear();
                ApplicationStore.getMenus().clear();
                ApplicationStore.getElements().clear();
                ApplicationStore.getPermissionMenus().clear();
                ApplicationStore.getRoles().clear();
                WSClient.getInstance().close();
            });
            btnCancel.setOnAction(event -> alert.close());
            alert.show();

        });

        rightMenuBar.getMenus().add(menuProfile);
        String avatar = ApplicationStore.getAvatar();

        if (StringUtils.isNotBlank(avatar)) {
            Image image;
            File f = null;
            try {
                f = File.createTempFile(UUID.randomUUID().toString(), ".png");
            } catch (IOException e) {
                e.printStackTrace();
            }
            ImageUtil.GenerateImage(avatar, f);
            if (f == null) {
                image = new Image(this.getClass().getResourceAsStream("/images/default-avatar.png"));
            } else {
                image = new Image(f.toURI().toString());
            }
            CFImage cfImage3 = new CFImage(image);
            cfImage3.setImageStyle(22,11);
            userAvatar.getChildren().add(cfImage3);
        }

    }

    /**
     * 处理自定义事件监听
     */
    private void initListener() {
        CustomEventManager.addListener(new CustomEventListener<SocketDataChangeEvent>() {

            /**
             * 处理器
             *
             * @param socketDataChangeEvent
             */
            @Override
            public void handler(SocketDataChangeEvent socketDataChangeEvent) {
                String text = ApplicationStore.getBellNumber();
                if(StringUtils.isBlank(text)){
                    text="1";
                }
                int integer = Integer.parseInt(text);
                integer = integer>99?99:integer++;
                int finalInteger = integer;
                Platform.runLater(() -> ApplicationStore.setBellNumber(String.valueOf(finalInteger)));
                JFXSnackbarLayout jfxSnackbarLayout = new JFXSnackbarLayout(socketDataChangeEvent.getTitle());
                snackbar.fireEvent(new JFXSnackbar.SnackbarEvent(jfxSnackbarLayout));
            }
        });

    }

}
